_Pragma("once");

#include <string>
#include <map>
#include <iostream>
#include <iomanip>

#include "CommandExecutor.h"
#include "LoopStatus.h"
#include "SingletonTemplate.h"
#include "CommandDispatcher.h"
#include "JsonCommandParser.h"
#include "MachineDependents.h"

class CommandDispatcher;

class CommandParser {
    friend class SingletonTemplate<CommandParser>;

public:

    /** Default destructor */
    ~CommandParser();


    /**
    * A指令 写入特定时间段内的开关操作
    * @param detailCmd, std::string& result 指令内容
    */
    void onSpecialTimeOperated(NetworkString& detailCmd, std::string& result) {
        detailCmd.erase(0, 4);
        detailCmd.erase(detailCmd.length() - 2, 2);

        mcommandExecutor.onSpecialTimeOperated(detailCmd, result);
        detailCmd = "<A>";
    }

    /**
     * B指令 申请本地储存数据操作
     * @param detailCmd, std::string& result 指令内容
     */
    void onRequestOfflineCommand(NetworkString& detailCmd, std::string& result) {
        result.reserve(STRING_BUFFER_SIZE * 12);
        std::string message;
        message.reserve(STRING_BUFFER_SIZE);

        std::tm dateTime = DateTimeUtility::getTime();
        for (int i = 0;  i < 12; ++i) {
            dateTime.tm_mon = i;
            mcommandExecutor.onRequestOfflineCommand(dateTime, message);
            message.insert(0, "B_");

            build(detailCmd, message, true, true);
            result.append(message);

            message.clear();
        }

        result.append("<H>\r\n");

    }

    /**
     * C指令 写入备选IP地址和端口号

     * @param detailCmd, std::string& result 指令内容
     */
    void onWriteBackupServerPort(NetworkString& detailCmd, std::string& result) {}

    /**
     * D指令 删除本地开关操作存储
     * @param detailCmd, std::string& result 指令内容
     */
    void onDeleteLocalSwitch(NetworkString& detailCmd, std::string& result) {
        mcommandExecutor.onDeleteLocalSwitch(result);
    }

    /**
     * E指令 设置当天定时器指令
     * @param detailCmd, std::string& result 指令内容
     */
    void onTodayTimer(NetworkString& detailCmd, std::string& result) {}

    /**
     * F指令 获取经纬度
     * @param detailCmd, std::string& result 指令内容
     */
    void onNewRequestLocation(NetworkString& detailCmd, std::string& result) {
        mcommandExecutor.onNewRequestLocation(detailCmd, result);
    }


    /**
     * G指令 获取经纬度
     * @param detailCmd, std::string& result 指令内容
     */
    void onRequestLocation(NetworkString& detailCmd, std::string& result) {}

    /**
     * H指令 写入系统时间
     * @param detailCmd, std::string& result 指令内容
     */
    void onWriteTime(NetworkString& detailCmd, std::string& result) {

        mcommandExecutor.onWriteTime(detailCmd.substr(3));
    }

    /**
     * I指令  读取系统时间
     * @param detailCmd, std::string& result 指令内容
     */
    void onReadTime(NetworkString& detailCmd, std::string& result) {
        mcommandExecutor.onReadTime(result);
    }

    /**
     * J指令 用于查询开关状态
     * @param detailCmd, std::string& result 指令内容
     */
    void onCheckSwitch(NetworkString& detailCmd, std::string& result) {
        mcommandExecutor.onCheckSwitch(result);
    }

    /**
     * K指令 操作16路开关
     * @param detailCmd, std::string& result 指令内容
     */
    void onChannelOperated(NetworkString& detailCmd, std::string& result);


    /**
     * L指令获取通道数
     * @param detailCmd, std::string& result 指令内容
     */
    void onChannel(NetworkString& detailCmd, std::string& result) {

        size_t count = mcommandExecutor.onChannel();
        std::ostringstream oss;
        oss << std::setw(3) << std::setfill('0') << count;

        result.append(oss.str());
    }

    /**
     * m指令强行将手动状态切换到自动状态
     * @param detailCmd, std::string& result 指令内容
     */
    void onOperatedState(NetworkString& detailCmd, std::string& result) {}
    /**
     * N指令 获取其他回路的电压电流信息
     * @param detailCmd, std::string& result 指令内容
     */
    void onExtendCurrentAndVoltage(NetworkString& detailCmd, std::string& result) {}

    /**
     * O指令获取们的开关状态
     * @param detailCmd, std::string& result 指令内容
     */
    void onDoorStatus(NetworkString& detailCmd, std::string& result) {
        result = "door_";

        mcommandExecutor.onDoorStatus(detailCmd, result);

    }

    /**
     * p指令获取光照强度
     * @param detailCmd, std::string& result 指令内容
     */
    void onSunLight(NetworkString& detailCmd, std::string& result) {
        mcommandExecutor.onSunLight(detailCmd, result);
    }

    /**
     * q指令信号强度
     * @param detailCmd, std::string& result 指令内容
     */
    void onNetworkState(NetworkString& detailCmd, std::string& result) {
        mcommandExecutor.onNetworkState(detailCmd, result);
    }

    /**
     * T指令读取终端工作环境温度
     * @param detailCmd, std::string& result 指令内容
     */
    void onTemperature(NetworkString& detailCmd, std::string& result) {

        std::string::size_type length = detailCmd.size(), prevfixLength = 3 == length ? 2 : 3;

        mcommandExecutor.onTemperature(detailCmd.substr(prevfixLength, length - prevfixLength - 1), result);
    }

    /**
     * U指令获取回路电流电压
     * @param detailCmd, std::string& result 指令内容
     */
    void onCurrentAndVoltage(NetworkString& detailCmd, std::string& result) {
        mcommandExecutor.onCurrentAndVoltage(detailCmd, result);
    }

    /**
     * V指令获取系统软件版本号
     * @param detailCmd, std::string& result 指令内容
     */
    void onVersion(NetworkString& detailCmd, std::string& result) {
        mcommandExecutor.onVersion(result);
    }

    /**
     * W指令获取功率
     * @param detailCmd, std::string& result 指令内容
     */
    void onPower(NetworkString& detailCmd, std::string& result) {
        mcommandExecutor.onPower(detailCmd, result);
    }

    /**
     * X指令 获取deviceId
     * @param detailCmd, std::string& result 指令内容
     */
    void onRequestDeviceId(NetworkString& detailCmd, std::string& result) {
        mcommandExecutor.onRequestDeviceId(result);
    }

    /**
     * Y指令获取湿度指令
     * @param detailCmd, std::string& result 指令内容
     */
    void onHumidity(NetworkString& detailCmd, std::string& result) {}

    /**
     * Z指令模拟按键
     * @param detailCmd, std::string& result 指令内容
     */
    void simulatorKeyPress(NetworkString& detailCmd, std::string& result) {}

    /**
     * p指令，测试服务器时延
     * @param detailCmd, std::string& result 指令内容
     */
    void onPingBack(NetworkString& detailCmd, std::string& result) {}

    void notImplemented(NetworkString& detailCmd, std::string& result) {}

    void onJsonCommand(NetworkString& detailCmd, std::string& result) {
        mjsonCommandParser.parseCommand(detailCmd, result);
    }


    void requestOfflineCommand();

    void sendDoorStatus();

    void sendAcSwitchStatus(const std::string& switchMode, const std::string& loopSwitchStatus);

    void sendCurrentAndVoltage();

    void sendAlertInfo(const std::string& alertType, const std::string& data);

    void sendTemperatureAlarm(const std::string& threshold);


    using  CommandFunctionPointor = void (CommandParser::*)(NetworkString& detailCmd, std::string& result);

    void parseCommand(NetworkString& data, NetworkString& result);

    NetworkString& build(NetworkString& data, NetworkString& result, bool success, bool passive);
    void buildAndSend(NetworkString& data, NetworkString& result, bool success, bool passive);


    CommandExecutor& mcommandExecutor = CommandExecutorSingleton::instance();
    CommandDispatcher* mparentCommandDispatcher = nullptr;

    JsonCommandParser mjsonCommandParser;

protected:
    /** Default constructor */
    CommandParser();

    std::map<char, CommandFunctionPointor>  mcommandToFunction{
        {'A', &CommandParser::onSpecialTimeOperated}
        ,{'B', &CommandParser::onRequestOfflineCommand}
        ,{'C', &CommandParser::onWriteBackupServerPort}
        ,{'D', &CommandParser::onDeleteLocalSwitch}
        ,{'E', &CommandParser::onTodayTimer}
        ,{'F', &CommandParser::onNewRequestLocation}
        //not used now
        ,{'G', &CommandParser::notImplemented}
        ,{'H', &CommandParser::onWriteTime}
        ,{'I', &CommandParser::onReadTime}
        ,{'J', &CommandParser::onCheckSwitch}
        ,{'K', &CommandParser::onChannelOperated}
        ,{'L', &CommandParser::onChannel}
        ,{'M', &CommandParser::onOperatedState}
        ,{'N', &CommandParser::onExtendCurrentAndVoltage}
        ,{'O', &CommandParser::onDoorStatus}
        ,{'P', &CommandParser::onSunLight}
        ,{'Q', &CommandParser::onNetworkState}
        ,{'R', &CommandParser::notImplemented}
        ,{'S', &CommandParser::notImplemented}
        ,{'T', &CommandParser::onTemperature}
        ,{'U', &CommandParser::onCurrentAndVoltage}
        ,{'V', &CommandParser::onVersion}
        ,{'W', &CommandParser::onPower}
        ,{'X', &CommandParser::onRequestDeviceId}
        ,{'Y', &CommandParser::onHumidity}
        ,{'Z', &CommandParser::onJsonCommand}
        ,{'p', &CommandParser::onPingBack}
        ,{'a', &CommandParser::simulatorKeyPress}

    };
};


using CommandParserSingleton = class SingletonTemplate<CommandParser>;

